package bx.job.actors;

import akka.actor.typed.ActorRef;
import akka.actor.typed.Behavior;
import akka.actor.typed.javadsl.AbstractBehavior;
import akka.actor.typed.javadsl.ActorContext;
import akka.actor.typed.javadsl.Behaviors;
import akka.actor.typed.javadsl.Receive;
import bx.job.JobServerBootstrap;
import bx.job.entity.BxJobInfo;
import bx.job.entity.BxLogInfo;
import bx.job.entity.BxTriggerInfo;
import bx.job.jobstore.bean.JobInfoContextBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.CompletableFuture;

import static bx.job.entity.BxLogInfo.LOGGED_STATUS;

public class JobLogActor extends AbstractBehavior<JobLogActor.JobIssueActorMsg> {
    private final static Logger log = LoggerFactory.getLogger(JobLogActor.class);


    public interface JobIssueActorMsg {
    }

    public record JobIssueMsg(JobInfoContextBean jobInfoContext,
                              ActorRef<JobProcessManagerActor.JobProcessManagerActorMsg> replyTo) implements JobLogActor.JobIssueActorMsg {
    }

    public record UpdateJobStatusWithErrorCodeMsg(BxLogInfo logInfo) implements JobLogActor.JobIssueActorMsg {
    }

    public record UpdateJobRetryCount(BxLogInfo logInfo) implements JobLogActor.JobIssueActorMsg {
    }

    public static Behavior<JobLogActor.JobIssueActorMsg> create() {
        return Behaviors.setup(JobLogActor::new);
    }

    private JobLogActor(ActorContext<JobLogActor.JobIssueActorMsg> context) {
        super(context);
    }

    @Override
    public Receive<JobLogActor.JobIssueActorMsg> createReceive() {
        return newReceiveBuilder().onMessage(JobLogActor.JobIssueMsg.class, this::onJobIssueMsg)
                .onMessage(JobLogActor.UpdateJobStatusWithErrorCodeMsg.class, this::onUpdateJobStatusWithErrorCodeMsg)
                .onMessage(JobLogActor.UpdateJobRetryCount.class, this::onUpdateJobRetryCount)
                .build();
    }

    private Behavior<JobIssueActorMsg> onUpdateJobRetryCount(UpdateJobRetryCount updateJobRetryCount) {
        // TODO 调用 job 接口更新
        return this;
    }

    private Behavior<JobIssueActorMsg> onUpdateJobStatusWithErrorCodeMsg(UpdateJobStatusWithErrorCodeMsg updateJobInfoMsg) {
        // TODO 调用 job 接口更新
        return this;
    }


    private Behavior<JobIssueActorMsg> onJobIssueMsg(JobIssueMsg jobIssueMsg) {
        JobInfoContextBean jobInfoContext = jobIssueMsg.jobInfoContext();
        BxJobInfo bxJobInfo = jobInfoContext.getBxJobInfo();
        BxTriggerInfo triggerInfo = jobInfoContext.getTriggerInfo();
        CompletableFuture.supplyAsync(() -> {
            log.info("start record log for job : {}", jobInfoContext);
            long currentTime = System.nanoTime();
            BxLogInfo logInfo = BxLogInfo.builder()
                    .jobId(bxJobInfo.getJobId())
                    .jobDescription(bxJobInfo.getJobDescription())
                    .createTime(currentTime)
                    .updateTime(currentTime)
                    .status(LOGGED_STATUS)
                    .triggerId(triggerInfo.getTriggerId())
                    .routeStrategyName(bxJobInfo.getRouteStrategyName())
                    .build();
            JobServerBootstrap.getLogStore().saveJobLog(logInfo);
            return logInfo;
        }).whenComplete((logInfo, error) -> {
            if (error == null) {
                log.info("record log success");
                jobInfoContext.setLogInfo(logInfo);
                jobInfoContext.setLogActor(this.getContext().getSelf());
                jobIssueMsg.replyTo().tell(new JobProcessManagerActor.JobLoggedMsg(jobInfoContext));
            } else {
                log.info("record log failed, will discard this job：{}", jobInfoContext);
            }
        });
        return this;
    }

}
